package com.fhzn.auth.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fhzn.auth.constant.Constants;
import com.fhzn.auth.entity.Resource;
import com.fhzn.auth.enums.WebResponseEnum;
import com.fhzn.auth.mapper.ResourceMapper;
import com.fhzn.auth.service.OperatorLogService;
import com.fhzn.auth.service.ResourceService;
import com.fhzn.auth.service.RoleService;
import com.fhzn.auth.web.converter.ResourceConverter;
import com.fhzn.auth.web.request.ResourceOpRequest;
import com.fhzn.auth.web.request.ResourceQueryRequest;
import com.fhzn.auth.web.vo.ResourceVO;
import com.fhzn.commons.toolkit.exception.BuzException;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author 老顾
 * @apiNote
 * @since 2023/12/20
 */
@Service
@RequiredArgsConstructor
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements ResourceService {

    private final ResourceMapper resourceMapper;
    private final RoleService roleService;
    private final OperatorLogService operatorLogService;

    @Override
    public Page<Resource> resourceWithPage(ResourceQueryRequest request) {
        request.setAppCode(request.getInvokeAppName());
        request.checkParams();
        request.rewriteParams();
        request.getOffset();
        return resourceMapper.getResourcesByPage(request);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResourceVO addResource(ResourceOpRequest request) {
        request.checkBaseParams();
        request.setAppCode(request.getInvokeAppName());
        request.checkAdd();
        Resource resource = request.addGenServiceParam();
        this.addResourceInfo(resource, request.getHandler());
        operatorLogService.operatorLog(request.getHandler(),
                Constants.RESOURCE_SECTION, Constants.RESOURCE_ADD_METHOD, resource.getId(), null,
                resourceMapper.getResourceByCodeAndAppCode(request.getCode(), request.getAppCode()), Constants.AUTH_APP_CODE);
        return ResourceConverter.fromResource(resource);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateResource(ResourceOpRequest request) {
        request.checkBaseParams();
        request.setAppCode(request.getInvokeAppName());
        request.checkUpdate();
        Resource resourceBefore = resourceMapper.selectById(request.getId());
        if (resourceBefore == null) {
            throw new BuzException("资源不存在");
        }
        if (!StringUtils.equals(resourceBefore.getAppCode(), request.getAppCode())) {
            throw new BuzException("资源 appcode 不允许修改");
        }
        // 更新资源
        this.updateResource(request.genServiceParam(), request.getHandler());
        // 记录操作日志
        operatorLogService.operatorLog(request.getHandler(), Constants.RESOURCE_SECTION,
                Constants.RESOURCE_UPDATE_METHOD, request.getId(), resourceBefore,
                resourceMapper.selectById(request.getId()), Constants.AUTH_APP_CODE);
        return WebResponseEnum.SUCCESS.getMessage();
    }

    @Override
    public String exportResource(ResourceQueryRequest request) {
        return null;
    }

    @Override
    public String importResource(ResourceQueryRequest request) {
        return null;
    }

    /**
     * 增加资源信息
     *
     * @param resource 资源请求
     * @param handler  用户昵称
     */
    private void addResourceInfo(Resource resource, String handler) {
        if (roleService.isSuperAdminOrAdmin(handler, resource.getAppCode())) {
            this.prepareWrite(resource);
            resourceMapper.insert(resource);
        } else {
            throw new BuzException("无操作权限");
        }
    }

    /**
     * 更新资源信息
     *
     * @param resource 资源请求
     * @param handler  用户昵称
     */
    private void updateResource(Resource resource, String handler) {
        if (roleService.isSuperAdminOrAdmin(handler, resource.getAppCode())) {
            this.prepareWrite(resource);
            resourceMapper.updateById(resource);
        } else {
            throw new BuzException("无操作权限");
        }
    }

    /**
     * 准备写入
     *
     * @param resource 资源
     */
    public void prepareWrite(Resource resource) {
        if (StringUtils.isBlank(resource.getParentCode())) {
            resource.setLevel(0);
        } else {
            Resource parent = resourceMapper.getResourceByCodeAndAppCode(resource.getParentCode(), resource.getAppCode());
            if (parent == null) {
                throw new BuzException("父资源不存在");
            }
            resource.setLevel(parent.getLevel() == null ? 0 : parent.getLevel() + 1);
        }
    }

}
